package main

import (
	"database/sql"
	"fmt"
	"time"

	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

type Product struct {
	gorm.Model
	Code  string
	Price uint
}

type User struct {
	ID           uint           // Standard field for the primary key
	Name         string         // A regular string field
	Email        *string        // A pointer to a string, allowing for null values
	Age          uint8          // An unsigned 8-bit integer
	Birthday     *time.Time     // A pointer to time.Time, can be null
	MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
	ActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fields
	CreatedAt    time.Time      // Automatically managed by GORM for creation time
	UpdatedAt    time.Time      // Automatically managed by GORM for update time
	ignored      string         // fields that aren't exported are ignored
}

// `User` 属于 `Company`，`CompanyID` 是外键
type User2 struct {
	gorm.Model
	Name      string
	CompanyID int
	Company   Company
}

type Company struct {
	gorm.Model
	Name string
}

func main() {
	db := getDb()

	// 迁移 schema
	db.AutoMigrate(&Company{}, &User2{})

	result := db.Create(&User2{
		Name:    "jinzhu",
		Company: Company{Name: "google"},
	})

	fmt.Printf("RowsAffected: %d, Error: %v\n", result.RowsAffected, result.Error)
}

func mainUser() {
	db := getDb()

	// 迁移 schema
	db.AutoMigrate(&User{})

	//now := time.Now()
	//user := &User{Name: "Jinzhu", Age: 18, Birthday: &now}

	//result := db.Create(user) // 通过数据的指针来创建

	// Print the result
	//fmt.Printf("RowsAffected: %d, Error: %v\n", result.RowsAffected, result.Error)

	var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}
	db.Create(&users)

	for _, user := range users {
		fmt.Println(user.ID) // 1,2,3
	}
}

func mainProject() {
	db := getDb()

	// 迁移 schema
	db.AutoMigrate(&Product{})

	// Create
	db.Create(&Product{Code: "D42", Price: 100})

	// Read
	var product Product
	db.First(&product, 1)                 // 根据整型主键查找
	db.First(&product, "code = ?", "D42") // 查找 code 字段值为 D42 的记录

	// Update - 将 product 的 price 更新为 200
	db.Model(&product).Update("Price", 200)
	// Update - 更新多个字段
	db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // 仅更新非零值字段
	db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})

	// Delete - 删除 product
	//db.Delete(&product, 1)
}

func getDb() *gorm.DB {

	dsn := "host=localhost user=postgres password=1234qwer dbname=lab port=5436 sslmode=disable TimeZone=Asia/Shanghai"

	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	return db
}
